"""
Coze 对话功能 FastAPI 路由
集成 Coze SDK 实现智能客服对话
"""

from fastapi import APIRouter, HTTPException, Depends
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
import json
import asyncio
from datetime import datetime

try:
    from cozepy import Coze, TokenAuth, Message, ChatEventType, COZE_CN_BASE_URL
    COZE_AVAILABLE = True
except ImportError:
    COZE_AVAILABLE = False
    print("[警告] cozepy 未安装，Coze 功能将不可用。请运行: pip install cozepy")

from config.settings import settings

router = APIRouter(prefix="/api/coze", tags=["Coze对话"])

# 初始化 Coze 客户端
coze_client = None
if COZE_AVAILABLE:
    try:
        base_url = COZE_CN_BASE_URL if settings.COZE_USE_CN_BASE else None
        coze_client = Coze(
            auth=TokenAuth(token=settings.COZE_API_TOKEN),
            base_url=base_url
        )
        print("[OK] Coze 客户端初始化成功")
    except Exception as e:
        print(f"[错误] Coze 客户端初始化失败: {e}")
        coze_client = None


# ============ 请求/响应模型 ============

class CozeChatRequest(BaseModel):
    """Coze 对话请求"""
    message: str
    user_id: Optional[str] = "default_user"  # 用户ID，用于区分不同用户
    conversation_id: Optional[str] = None  # 对话ID，用于多轮对话


class CozeChatResponse(BaseModel):
    """Coze 对话响应"""
    success: bool
    message: str
    conversation_id: Optional[str] = None
    token_usage: Optional[Dict[str, Any]] = None


# ============ 工具函数 ============

def get_user_id(user_id: Optional[str] = None) -> str:
    """获取用户ID，如果未提供则使用默认值"""
    return user_id or "default_user"


# ============ API 路由 ============

@router.post("/chat", response_model=CozeChatResponse)
async def coze_chat(request: CozeChatRequest):
    """
    Coze 对话接口（非流式）
    
    功能：
    - 发送消息到 Coze Bot
    - 获取 AI 回复
    - 支持多轮对话
    
    参数：
    - message: 用户消息
    - user_id: 用户ID（可选，默认 "default_user"）
    - conversation_id: 对话ID（可选，用于多轮对话）
    
    返回：
    - success: 是否成功
    - message: AI 回复内容
    - conversation_id: 对话ID
    - token_usage: Token 使用情况
    """
    if not COZE_AVAILABLE or not coze_client:
        raise HTTPException(
            status_code=503,
            detail="Coze 服务不可用，请检查配置或安装 cozepy: pip install cozepy"
        )
    
    try:
        user_id = get_user_id(request.user_id)
        bot_id = settings.COZE_BOT_ID
        
        # 构建消息
        messages = [
            Message.build_user_question_text(request.message)
        ]
        
        # 调用 Coze API（非流式）
        # 注意：cozepy 的 stream 方法是同步的，我们需要在异步环境中运行
        response_content = ""
        token_usage = None
        
        # 使用 asyncio.to_thread 在后台线程中运行同步代码
        def run_coze_chat():
            """在后台线程中运行 Coze 对话"""
            content = ""
            usage = None
            try:
                for event in coze_client.chat.stream(
                    bot_id=bot_id,
                    user_id=user_id,
                    additional_messages=messages
                ):
                    if event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:
                        # 累积消息内容
                        if hasattr(event, 'message') and hasattr(event.message, 'content'):
                            content += event.message.content or ""
                    elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:
                        # 对话完成，获取 token 使用情况
                        if hasattr(event, 'chat') and hasattr(event.chat, 'usage'):
                            usage = {
                                "token_count": event.chat.usage.token_count if hasattr(event.chat.usage, 'token_count') else None
                            }
            except Exception as e:
                print(f"[Coze错误] 对话过程中出错: {e}")
                raise
            return content, usage
        
        # 在后台线程中执行
        response_content, token_usage = await asyncio.to_thread(run_coze_chat)
        
        if not response_content:
            raise HTTPException(status_code=500, detail="Coze 返回空响应")
        
        return CozeChatResponse(
            success=True,
            message=response_content,
            conversation_id=request.conversation_id or f"coze_{user_id}_{int(datetime.now().timestamp())}",
            token_usage=token_usage
        )
        
    except Exception as e:
        print(f"[Coze错误] 对话失败: {e}")
        import traceback
        traceback.print_exc()
        raise HTTPException(
            status_code=500,
            detail=f"Coze 对话失败: {str(e)}"
        )


@router.post("/chat/stream")
async def coze_chat_stream(request: CozeChatRequest):
    """
    Coze 对话接口（流式响应）
    
    功能：
    - 发送消息到 Coze Bot
    - 流式返回 AI 回复（实时显示）
    - 支持多轮对话
    
    返回格式（Server-Sent Events）：
    data: {"type": "delta", "content": "部分内容"}
    data: {"type": "done", "conversation_id": "xxx", "token_usage": {...}}
    """
    if not COZE_AVAILABLE or not coze_client:
        raise HTTPException(
            status_code=503,
            detail="Coze 服务不可用，请检查配置或安装 cozepy: pip install cozepy"
        )
    
    async def generate_stream():
        """生成流式响应"""
        try:
            user_id = get_user_id(request.user_id)
            bot_id = settings.COZE_BOT_ID
            
            # 构建消息
            messages = [
                Message.build_user_question_text(request.message)
            ]
            
            # 在后台线程中运行 Coze 流式对话
            def run_coze_stream():
                """在后台线程中运行 Coze 流式对话"""
                events = []
                try:
                    for event in coze_client.chat.stream(
                        bot_id=bot_id,
                        user_id=user_id,
                        additional_messages=messages
                    ):
                        events.append(event)
                except Exception as e:
                    print(f"[Coze错误] 流式对话过程中出错: {e}")
                    raise
                return events
            
            # 获取所有事件
            events = await asyncio.to_thread(run_coze_stream)
            
            # 流式发送事件
            conversation_id = request.conversation_id or f"coze_{user_id}_{int(datetime.now().timestamp())}"
            token_usage = None
            
            for event in events:
                if event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:
                    # 发送增量内容
                    content = ""
                    if hasattr(event, 'message') and hasattr(event.message, 'content'):
                        content = event.message.content or ""
                    
                    if content:
                        yield f"data: {json.dumps({'type': 'delta', 'content': content}, ensure_ascii=False)}\n\n"
                
                elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:
                    # 对话完成，发送完成消息
                    if hasattr(event, 'chat') and hasattr(event.chat, 'usage'):
                        token_usage = {
                            "token_count": event.chat.usage.token_count if hasattr(event.chat.usage, 'token_count') else None
                        }
                    
                    yield f"data: {json.dumps({'type': 'done', 'conversation_id': conversation_id, 'token_usage': token_usage}, ensure_ascii=False)}\n\n"
            
        except Exception as e:
            print(f"[Coze错误] 流式对话失败: {e}")
            import traceback
            traceback.print_exc()
            error_msg = json.dumps({
                'type': 'error',
                'message': f'Coze 对话失败: {str(e)}'
            }, ensure_ascii=False)
            yield f"data: {error_msg}\n\n"
    
    return StreamingResponse(
        generate_stream(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no"
        }
    )


@router.get("/health")
async def coze_health():
    """Coze 服务健康检查"""
    return {
        "available": COZE_AVAILABLE and coze_client is not None,
        "bot_id": settings.COZE_BOT_ID if COZE_AVAILABLE else None,
        "message": "Coze 服务正常" if (COZE_AVAILABLE and coze_client) else "Coze 服务不可用"
    }
